package org.cytoscape.myapp.cytoscape_app_v1.internal.model;

import java.awt.Component;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Vector;

import org.cytoscape.application.CyApplicationManager;
import org.cytoscape.group.CyGroupFactory;
import org.cytoscape.group.CyGroupManager;
import org.cytoscape.model.CyColumn;
import org.cytoscape.model.CyEdge.Type;
import org.cytoscape.model.CyNetwork;
import org.cytoscape.model.CyNode;
import org.cytoscape.myapp.cytoscape_app_v1.internal.UI.Constants;
import org.cytoscape.myapp.cytoscape_app_v1.internal.UI.Constants.Priority;
import org.cytoscape.myapp.cytoscape_app_v1.internal.UI.GroupsInfo;
import org.cytoscape.myapp.cytoscape_app_v1.internal.layouts.KKLayout.algorithms.KKNodeLayout;
import org.cytoscape.myapp.cytoscape_app_v1.internal.metrics.Facade;
import org.cytoscape.myapp.cytoscape_app_v1.internal.metrics.domain.TrustedRelationship;
import org.cytoscape.myapp.cytoscape_app_v1.internal.metrics.domain.User;
import org.cytoscape.myapp.cytoscape_app_v1.internal.metrics.domain.UserPositionMapping;
import org.cytoscape.myapp.cytoscape_app_v1.internal.model.attributes.AttributeMapping;
import org.cytoscape.myapp.cytoscape_app_v1.internal.tasks.groups.GroupsTaskFactory;
import org.cytoscape.myapp.cytoscape_app_v1.internal.tasks.groups.GroupsTaskFactoryGroups;
import org.cytoscape.myapp.cytoscape_app_v1.internal.tasks.groups.GroupsTaskFactorySimple;
import org.cytoscape.myapp.cytoscape_app_v1.internal.tasks.metrics.CalculateSocialMetricTaskFactory;
import org.cytoscape.myapp.cytoscape_app_v1.internal.tasks.visual.VisualTaskFactory;
import org.cytoscape.myapp.cytoscape_app_v1.internal.tasks.visualHideEdge.StateVisualEdge;
import org.cytoscape.myapp.cytoscape_app_v1.internal.tasks.visualHideEdge.VirtualEdgeTaskFactory;
import org.cytoscape.myapp.cytoscape_app_v1.internal.tasks.visualHideEdge.VisualVirtualEdge;
import org.cytoscape.myapp.cytoscape_app_v1.internal.visual.VisualInstanceDependecies;
import org.cytoscape.myapp.cytoscape_app_v1.internal.visual.VisualStyleDefault;
import org.cytoscape.view.model.CyNetworkView;
import org.cytoscape.work.TaskIterator;


public class NetworkSettings{

	
	private Long networkSUID;
	private Set<String> columnNamesSimple = new HashSet<String>();
	private Set<String> columnNamesGroups = new HashSet<String>();
	
	
	public static final String[] selectVisualOption = {"Social Cohesion","Social Influence","Social Similitary"};

	private InfoVisualOption infoVisualOption; 
	
	
	private List<Component> criteriaComponents = new ArrayList<Component>();
	private Constants.Priority groupSelection = Constants.Priority.Xor;
	private int selectedSimpleColumn = 0;
	private int selectedGroupsColumn = 0;
	private int selectedPriority = 0;
	
	private CyApplicationManager applicationManager;
	private CyNetwork cyNetwork;
	private StateCyGroups state;
	private CyGroupManager groupManager;
	private CyGroupFactory groupFactory;

	private VisualStyleDefault visualStyleDefault;
	private VisualInstanceDependecies visualInstanceDependecies;
	private KKNodeLayout kkNodeLayout;

	private UserPositionMapping mapping;
	private List<TrustedRelationship> relationship;
	
	private AttributeMapping attributeMapping;
	
	private StateVisualEdge stateEdge;
	
	public NetworkSettings(CyApplicationManager applicationManager, 
							CyGroupManager groupManager, 
							CyGroupFactory groupFactory, 
							VisualInstanceDependecies visualInstanceDependecies,
							KKNodeLayout kkNodeLayout){
		
		this.cyNetwork = applicationManager.getCurrentNetwork();
		this.groupManager =groupManager ;
		this.groupFactory = groupFactory;
		this.visualStyleDefault = new VisualStyleDefault(visualInstanceDependecies);
		this.setVisualInstanceDependecies(visualInstanceDependecies);
		this.kkNodeLayout = kkNodeLayout;
	
		// ESTADO DE TODOS LOS ARCOS, COMIENZAN COMO OCULTOS
		//this.stateEdge = new HideVirtualEdge();
		this.stateEdge = new VisualVirtualEdge();
		this.applicationManager = applicationManager;
		this.networkSUID = applicationManager.getCurrentNetwork().getSUID();
		
		Collection<CyColumn> columns = applicationManager.getCurrentNetwork().getDefaultNodeTable().getColumns();
		
		for(CyColumn column:columns){
			if (column.getListElementType() != null){
				columnNamesGroups.add(column.getName());
			}
			else{
				if (!column.isImmutable())
					columnNamesSimple.add(column.getName());
			}
		}
			
		this.state = new StateExpanded(this.applicationManager);
		this.attributeMapping = new AttributeMapping(applicationManager);

	}
	
	

	public Long getNetworkSUID() {
		return networkSUID;
	}

	public void setNetworkSUID(Long networkSUID) {
		this.networkSUID = networkSUID;
	}

	public Set<String> getColumnNamesSimple() {
		return columnNamesSimple;
	}

	public void setColumnNamesSimple(Set<String> columnNamesSimple) {
		this.columnNamesSimple = columnNamesSimple;
	}

	public Set<String> getColumnNamesGroups() {
		return columnNamesGroups;
	}

	public void setColumnNamesGroups(Set<String> columnNamesGroups) {
		this.columnNamesGroups = columnNamesGroups;
	}

	public List<Component> getCriteriaComponents() {
		return criteriaComponents;
	}

	public void setCriteriaComponents(List<Component> criteriaComponents) {
		this.criteriaComponents = criteriaComponents;
	}
	
	public void addCriteriaComponents(Component subComponents) {
		this.criteriaComponents.add(subComponents);
	}
	
	public void setEnabledSubComponent(boolean enable){
		List<Component> components = this.criteriaComponents;
		for(Component como:components){
			como.setEnabled(enable);
		}
	}
	public void removeCriteriaComponents(Component subComponents) {
		this.criteriaComponents.remove(subComponents);
	}

	public Constants.Priority getGroupSelection() {
		return groupSelection;
	}

	public void setGroupSelection(Constants.Priority groupSelection) {
		this.groupSelection = groupSelection;
	}

	public int getSelectedSimpleColumn() {
		return selectedSimpleColumn;
		
	}
	
	public String getNameColumnNamesSimple(int simpleColumn){
		String valor= "";
		boolean corte = false;
		int cont =0;
		Iterator< String> it = columnNamesSimple.iterator();
		while(it.hasNext()&& !(corte)){
			
			if (cont == simpleColumn){ 
					valor =it.next();
					corte= true;
			}
			if (!corte)
					it.next();
			cont++;
		}
	return valor;
	}
	
	public String getNameColumnNamesGroup(int simpleColumn){
		String valor= "";
		boolean corte = false;
		int cont =0;
		Iterator< String> it = columnNamesGroups.iterator();
		while(it.hasNext()&& !(corte)){
			
			if (cont == simpleColumn){ 
					valor =it.next();
					corte= true;
			}
			if (!corte)
					it.next();
			cont++;
		}
	return valor;
	}
	
	public TaskIterator getTaskIteratorSimple(){
		
		GroupsTaskFactory groupTaskIterator = new GroupsTaskFactorySimple(applicationManager, groupManager, 
				groupFactory, getNameColumnNamesSimple(getSelectedSimpleColumn())); 
		
		
		return groupTaskIterator.createTaskIterator();
	}

	public TaskIterator getTaskIteratorGroup(){
		
		Component[] componentes = new Component[criteriaComponents.size()];
		criteriaComponents.toArray(componentes);
		GroupsInfo groupsInfo = new GroupsInfo((String) getNameColumnNamesGroup(getSelectedGroupsColumn()), (Priority) groupSelection);

		GroupsTaskFactory groupTaskIterator = new GroupsTaskFactoryGroups(applicationManager, groupManager, 
				groupFactory, getNameColumnNamesSimple(getSelectedSimpleColumn()),componentes,groupsInfo); 
	
		
		return groupTaskIterator.createTaskIterator();
	}
	
	public TaskIterator getTaskIteratorMetrics(){
		this.mapping = this.getUserPositionMapping();
		this.relationship = this.state.getListTrustedRelationships();
		CalculateSocialMetricTaskFactory calculateSocialMetricTaskFactory = 
					new CalculateSocialMetricTaskFactory(new Facade(this.mapping, this.relationship), applicationManager);
		
		return calculateSocialMetricTaskFactory.createTaskIterator();
	}
	
	public TaskIterator getTaskIteratorVisualStyle(){
		
		VisualTaskFactory visualTaskFactory = 
				new VisualTaskFactory(applicationManager, this.getTaskIteratorMetrics(), this.kkNodeLayout, this.infoVisualOption, visualStyleDefault);
		return visualTaskFactory.createTaskIterator();

	}
	
	// esconder o visualizar los arcos virtuales generados DEPENDIENDO DEL DEL ESTADO EN QUE SE ENCUENTRE "STATEEDGE"
	public TaskIterator getTaskIteratorVirtualEdge(){
		VirtualEdgeTaskFactory virtualEdgeTaskFactory = new VirtualEdgeTaskFactory(applicationManager,stateEdge);
		return virtualEdgeTaskFactory.createTaskIterator();
	}
	
	//CAMBIO EL ESTADO DE LOS ARCOS VIRTUALES, PARA QUE SEAN OCULTOS O VISIBLES
	public void changeStateVirtualEdge(){
		stateEdge = stateEdge.nextStateVisible_hide_Edge();
	}
	
	public void setSelectedSimpleColumn(int selectedSimpleColumn) {
		this.selectedSimpleColumn = selectedSimpleColumn;
	}

	public int getSelectedGroupsColumn() {
		return selectedGroupsColumn;
	}

	public void setSelectedGroupsColumn(int selectedGroupsColumn) {
		this.selectedGroupsColumn = selectedGroupsColumn;
	}

	public int getSelectedPriority() {
		return selectedPriority;
	}

	public void setSelectedPriority(int selectedPriority) {
		this.selectedPriority = selectedPriority;
	}

	public StateCyGroups getState() {
		return state;
	}

	public void setState() {
		this.state = this.state.getNextState();
		this.state.setCyGroupManager(groupManager);	
	}
	
	public void setFirstState(StateCyGroups state){
		this.state = state;
		this.state.setCyGroupManager(groupManager);
	}
	
	public UserPositionMapping getUserPositionMapping(){
		HashMap<String, User> usuarios = new HashMap<String, User>();
		List<CyNode> nodes = this.state.getNodes();
		for(CyNode node:nodes){
			User usuario = this.attributeMapping.getUserByCyNode(node);			
			usuario.setSuid(node.getSUID());
    		usuario.setId(this.cyNetwork.getDefaultNodeTable().getRow(node.getSUID()).get("name", String.class));
			List<CyNode> amigos = this.cyNetwork.getNeighborList(node, Type.ANY);
			List<String> friends = new Vector<String>();
			for (CyNode amigo:amigos){
				friends.add(this.cyNetwork.getDefaultNodeTable().getRow(amigo.getSUID()).get("name", String.class));
			}
			usuario.setFriends(friends);
			usuarios.put(usuario.getId(), usuario);
		}
		return new UserPositionMapping(usuarios);
	}

	public VisualInstanceDependecies getVisualInstanceDependecies() {
		return visualInstanceDependecies;
	}

	
	public void setVisualInstanceDependecies(VisualInstanceDependecies visualInstanceDependecies) {
		this.visualInstanceDependecies = visualInstanceDependecies;
	}

	public CyNetwork getCurrentNetwork() {
		return applicationManager.getCurrentNetwork();
	}
	public CyNetworkView getCurrentNetworkView() {
		return applicationManager.getCurrentNetworkView();
	}

//	public void applyVisualStyle() {
//		visualStyleDefault.setVisualMappingAttribute(this.infoVisualOption.getEdgeWith(), this.infoVisualOption.getEdgeColor());
//		visualStyleDefault.setVisualMappingFunction();
//		visualStyleDefault.applyVisualStyle();
//	}
	
	public void setVisualOptions(InfoVisualOption infoVisualOption){
		this.infoVisualOption = infoVisualOption;
	}
	
	public InfoVisualOption getVisualOptions(){
		return this.infoVisualOption;
	}
	
	public void setAttributeMapping(AttributeMapping attributeMapping){
		this.attributeMapping = attributeMapping;
	}
	
	public AttributeMapping getAttributeMapping(){
		return this.attributeMapping;
	}
}
